package com.tamartech.greendb.ui.views;

import java.awt.BorderLayout;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import org.springframework.binding.value.ValueModel;
import org.springframework.richclient.application.PageComponentContext;
import org.springframework.richclient.application.support.AbstractView;
import org.springframework.richclient.command.ActionCommand;
import org.springframework.richclient.command.ActionCommandExecutor;
import org.springframework.richclient.command.CommandGroup;
import org.springframework.richclient.command.GuardedActionCommandExecutor;
import org.springframework.richclient.command.support.AbstractActionCommandExecutor;
import org.springframework.richclient.command.support.GlobalCommandIds;
import org.springframework.richclient.list.ListSelectionValueModelAdapter;
import org.springframework.richclient.list.ListSingleSelectionGuard;
import org.springframework.richclient.table.support.AbstractObjectTable;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.TextFilterator;
import ca.odell.glazedlists.swing.TextComponentMatcherEditor;

import com.tamartech.greendb.ui.dialogs.AbstractPropertiesDialog;

public abstract class AbstractTableView extends AbstractView
{

    /**
     * Handler for the "Properties" action.
     */
    protected GuardedActionCommandExecutor editObjectExecutor = new EditObjectExecutor();
    
    
    /**
     * The text field allowing the user to filter the contents of the contact table.
     */
    protected JTextField filterField;

    protected String messagePrefix;
    
    public AbstractTableView (String messagePrefix)
    {
        super();
        
        this.messagePrefix = messagePrefix;
    }

    protected abstract AbstractObjectTable getObjectTable();
    protected abstract AbstractPropertiesDialog getEditObjectDialog();
    protected abstract String[] getFilterProperties();
    
    /**
     * Register the local command executors to be associated with named commands. This is called by the platform prior
     * to making the view visible.
     */
    protected void registerLocalCommandExecutors(PageComponentContext context)
    {
        context.register(GlobalCommandIds.PROPERTIES, editObjectExecutor);
    }

    @SuppressWarnings("unchecked")
    public void configureObjectTable ()
    {
        AbstractObjectTable objectTable = getObjectTable();
        
        EventList baseList = objectTable.getBaseEventList();
        TextFilterator filterator = GlazedLists.textFilterator(getFilterProperties());
        FilterList filterList = new FilterList(baseList, new TextComponentMatcherEditor(filterField, filterator));

        objectTable.setFinalEventList(filterList);
        
        // Register to get notified when the filtered list changes
        objectTable.setStatusBar(getStatusBar());
      
        CommandGroup popup = new CommandGroup();
        popup.add((ActionCommand) getWindowCommandManager().getCommand(GlobalCommandIds.PROPERTIES, ActionCommand.class));
        objectTable.setPopupCommandGroup(popup);
  
        // Ensure our commands are only active when something is selected.
        // These guard objects operate by inspecting a list selection model
        // (held within a ValueModel) and then either enabling or disabling the
        // guarded object (our executors) based on the configured criteria.
        // This configuration greatly simplifies the interaction between commands
        // that require a selection on which to operate.
        ValueModel selectionHolder = new ListSelectionValueModelAdapter(objectTable.getSelectionModel());
        new ListSingleSelectionGuard(selectionHolder, editObjectExecutor);

        objectTable.setDoubleClickHandler(editObjectExecutor);
    }
    
    /**
     * Create the control for this view. This method is called by the platform in order to obtain the control to add to
     * the surrounding window and page.
     * @return component holding this view
     */
    protected JComponent createControl()
    {
        JPanel filterPanel = new JPanel(new BorderLayout());
        JLabel filterLabel = getComponentFactory().createLabel(messagePrefix + ".filter.label");
        filterPanel.add(filterLabel, BorderLayout.WEST);
    
        String tip = getMessage(messagePrefix + ".filter.caption");
        filterField = getComponentFactory().createTextField();
        filterField.setToolTipText(tip);
        filterPanel.add(filterField, BorderLayout.CENTER);
        filterPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    
        configureObjectTable();
    
        JPanel view = new JPanel(new BorderLayout());
        JScrollPane sp = getComponentFactory().createScrollPane (getObjectTable().getControl());
        view.add(filterPanel, BorderLayout.NORTH);
        view.add(sp, BorderLayout.CENTER);
        return view;
    }

    /**
     * Private inner class to handle the properties form display.
     */
    class EditObjectExecutor extends AbstractActionCommandExecutor
    {
        public void execute()
        {
            // We know exactly one contact will be selected at this time because
            // of the guards put in place in prepareTable.
            getEditObjectDialog().showDialog();
        }
    }
}